package com.mayfool.gitmanager.core.manager;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mayfool.gitmanager.core.helper.LogHelper;
import com.mayfool.gitmanager.core.entity.ProjectInfo;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 项目管理器
 * 
 * @author zhou.xu
 * @date 2024-01-08 10:30:00
 * 
 * 该类提供了项目管理的核心功能，包括：
 * 1. 项目列表的维护和管理
 * 2. 项目的扫描和发现
 * 3. 项目信息的持久化（JSON格式）
 * 4. 远程仓库URL的解析
 * 
 * 使用CopyOnWriteArrayList确保线程安全
 * 实现了单例模式，所有方法都是静态的
 */
public class ProjectManager {

    /**
     * 项目列表，使用CopyOnWriteArrayList保证线程安全
     * 存储所有被管理的项目信息
     */
    private static final List<ProjectInfo> projects = new CopyOnWriteArrayList<>();

    /**
     * 获取项目列表的副本
     * 返回新的ArrayList以避免外部修改影响内部状态
     * 
     * @return 项目列表副本
     */
    public static List<ProjectInfo> getProjects() {
        return new ArrayList<>(projects);
    }

    /**
     * 添加新项目到管理器
     * 如果项目已存在或为null则不添加
     * 
     * @param projectInfo 项目信息对象
     */
    public static void addProject(ProjectInfo projectInfo) {
        if (projects.contains(projectInfo))
            return;
        if (projectInfo == null)
            return;
        projects.add(projectInfo);
        LogHelper.getInstance().append("新增项目: ").append(projectInfo.getName()).append("\t").append(projectInfo.getRemoteUrl()).append("\n");
    }

    /**
     * 扫描指定目录下的所有Git项目
     * 将发现的项目添加到管理器并保存到JSON文件
     * 
     * @param directory 要扫描的根目录
     */
    public static void scanExistingProjects(File directory) {
        try {
            scanGitRepositories(directory.toPath());
            saveToJson();
        } catch (IOException e) {
            LogHelper.getInstance().append("扫描失败: ").append(e.getMessage()).append("\n");
        }
    }

    /**
     * 递归扫描目录查找Git仓库
     * 使用Files.walkFileTree实现目录遍历
     * 
     * @param rootDir 根目录路径
     * @throws IOException 如果发生IO错误
     */
    private static void scanGitRepositories(Path rootDir) throws IOException {
        Files.walkFileTree(rootDir, new SimpleFileVisitor<>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                if (dir.endsWith(".git")) {
                    Path projectPath = dir.getParent();
                    String remoteUrl = getRemoteRepositoryUrl(dir.toFile());
                    addProject(new ProjectInfo(
                            projectPath.getFileName().toString(),
                            projectPath.toAbsolutePath().toString(),
                            remoteUrl
                    ));
                    return FileVisitResult.SKIP_SIBLINGS;
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    /**
     * 获取Git仓库的远程URL
     * 使用JGit API读取仓库配置
     * 
     * @param gitDir .git目录
     * @return 远程仓库URL，如果获取失败则返回空字符串
     */
    private static String getRemoteRepositoryUrl(File gitDir) {
        try (Repository repository = new FileRepositoryBuilder().setGitDir(gitDir).build()) {
            return repository.getConfig().getString("remote", "origin", "url");
        } catch (Exception e) {
            LogHelper.getInstance().append("获取远程地址失败: ").appendLine(gitDir);
            return "";
        }
    }

    /**
     * 将项目列表保存为JSON文件
     * 使用Jackson库进行序列化
     * 文件保存在当前用户目录下的projects.json
     */
    private static void saveToJson() {
        ObjectMapper mapper = new ObjectMapper();
        try {
            mapper.writeValue(new File(System.getProperty("user.dir"), "projects.json"), projects);
        } catch (IOException e) {
            LogHelper.getInstance().append("JSON保存失败: ").appendLine(e.getMessage());
        }
    }

    /**
     * 从JSON文件加载项目列表
     * 在类加载时通过静态代码块调用
     * 如果文件不存在或加载失败，项目列表保持为空
     */
    private static void loadFromJson() {
        ObjectMapper mapper = new ObjectMapper();
        File jsonFile = new File(System.getProperty("user.dir"), "projects.json");
        if (jsonFile.exists()) {
            try {
                List<ProjectInfo> projectInfos = mapper.readValue(jsonFile, new TypeReference<List<ProjectInfo>>() {});
                projects.addAll(projectInfos);
            } catch (IOException e) {
                LogHelper.getInstance().append("JSON加载失败: ").appendLine(e.getMessage());
            }
        }
    }

    /**
     * 静态初始化块
     * 在类加载时自动从JSON文件加载已保存的项目列表
     */
    static {
        loadFromJson();
    }
}
